package gn.eugene.list;

/**
 * Eugene Java Core Live
 */

import gn.eugene.list.utils.WrongPageIndexException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class ListPage {

    private List<Item> itemList;
    private List<Item> insertList;
    private List<Integer> deleteList;

    ListPage() {
        itemList = new ArrayList<Item>();
        insertList = new ArrayList<Item>();
        deleteList = new ArrayList<Integer>();
    }

    public void insert(int position, int sizePage, int page, String value) throws WrongPageIndexException {
        if (page == 0) {
            throw new WrongPageIndexException("Page index can't be zero!");
        }

        int absolutPosition = absolutePostion(page, sizePage, position);
        searchInsertItem(absolutPosition, -1);

        insertList.add(new Item(absolutPosition, value));
    }

    public void delete(int position, int sizePage, int page) {
        int absolutPosition = absolutePostion(page, sizePage, position);

        deleteList.add(absolutPosition);

        for (int i = 0; i < insertList.size(); i++) {
            if (insertList.get(i).getPosition() == absolutPosition) {
                insertList.remove(i);
            }
        }
    }

    public List<Item> list(int sizePage, int page) {
        List<Item> outList = new ArrayList<Item>();
        Item tempItem;
        tempItem = null;

        int absolutPosition = absolutePostion(page, sizePage);
        int currentPosition;
        int coefficientPosition = countInsertandDeleteItem(absolutPosition);

        absolutPosition = Math.abs(absolutPosition - coefficientPosition);

        int length = absolutPosition + sizePage;


        for (int i = absolutPosition; i < length; i++) {

            currentPosition = i - absolutPosition;
            //tempItem = getInsertItem(i + coefficientPosition);
            tempItem = getInsertItem(i);

            if (tempItem != null) {
                outList.add(tempItem);
            } else {
                if (isDeleteItem(i) && length < itemList.size()) {
                    length++;
                } else {
                    outList.add(itemList.get(i));
                }
            }
            //outList.addAll(currentPosition, searchInsertItem(i + coefficientPosition));
        }

        for (int i = outList.size() - 1; i >= sizePage; i--) {
            outList.remove(i);
        }
        return outList;
    }

    public List<String> listOfString(int sizePage, int page) {
        List<String> outStrings = new ArrayList<String>();

        for (Item i : list(sizePage, page)) {
            outStrings.add(i.getValue());
        }

        return outStrings;

    }

    private int absolutePostion(int page, int sizePage) {
        return absolutePostion(page, sizePage, 0);
    }

    private int absolutePostion(int page, int sizePage, int position) {
        return sizePage * (page - 1) + position;
    }

    private boolean isDeleteItem(int index) {
        for (int k = 0; k < deleteList.size(); k++) {
            if (deleteList.get(k) == index) {
                return true;
            }
        }
        return false;
    }

    private Item getInsertItem(int index) {
        for (Item i : insertList) {
            if (i.getPosition() == index) {
                return i;
            }
        }
        return null;
    }

    private void searchInsertItem(int newPositionItem, int cycleOfPosition) {
        for (int i = 0; i < insertList.size(); i++) {
            if (insertList.get(i).getPosition() == newPositionItem
                    && cycleOfPosition != i) {
                insertList.get(i).setPosition(insertList.get(i).getPosition() + 1);
                searchInsertItem(insertList.get(i).getPosition(), i);
                break;
            }
        }
    }

    public int countInsertandDeleteItem(int toPosition) {
        int count = 0;

        for (Item i : insertList) {
            if (toPosition > i.getPosition()) {
                count++;
            }
        }
        for (Integer i : deleteList) {
            if (toPosition > i) {
                count--;
            }
        }

        return count;
    }

    public void addList(Collection<String> e) {
        for (String a : e) {
            itemList.add(new Item(a));
        }
    }

    public List<Item> getInsert() {
        return insertList;
    }
}
